package pratice.fengzhongye.interview;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 面试题：多线程，写一个生产者消费者。这个是没有看答案自己写的，为什么错误？
 *
 * 首先synchronized是获得当前对象的锁，所以生产和消费都应该是同一个类里面的不同的方法，所以应该抽象成product类。
 * 而线程调用的只是Product对象的生产方法和消费方法。
 *
 * 我下面写的是生产是在一个类，消费是在一个类，锁是锁一个静态变量。为什么会抛出IllegalMonitorStateException异常呢？
 * 因为调用notifyAll的当前对象没有拥有锁资源
 *
 * @author 吴宇亮 on 2019/2/19 0019 14:31
 */
public class Lesson11_Thread {

    //产品数量, 打印010101
    public static int amount;
    public static Object lock = new Object();

    public static void main(String[] args) {

        //创建10个生产者
        List<Thread> producters = new ArrayList<>();
        List<Thread> comsumers = new ArrayList<>();
        for(int i = 0; i < 10; i++){
            producters.add(new Producter());
            comsumers.add(new Comsumer());
        }

        producters.forEach(item -> item.start());
        comsumers.forEach(item -> item.start());
    }

    @Test
    public void test(){
        new Object().notify();
    }

    @Test
    public void test2() throws InterruptedException {
        new Object().wait();
    }
}

class Producter extends Thread{
    @Override
    public void run() {
        synchronized (Lesson11_Thread.lock){
            //产品满了, 通知消费者进行消费
            if(Lesson11_Thread.amount == 1){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                System.out.println("Producter: " + Lesson11_Thread.amount);
                Lesson11_Thread.amount++;
                this.notifyAll();
            }
        }
    }
}

class Comsumer extends Thread{
    @Override
    public void run() {
        synchronized (Lesson11_Thread.lock){
            if(Lesson11_Thread.amount == 0){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                System.out.println("Comsumer: " + Lesson11_Thread.amount);
                Lesson11_Thread.amount--;
                this.notifyAll();
            }
        }
    }
}

